package com.ebrg.secure9.activity.setup;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.text.InputType;
import android.view.KeyEvent;
import android.widget.EditText;
import android.widget.Toast;

import com.ebrg.secure9.Account;
import com.ebrg.secure9.Secure9;
import com.ebrg.secure9.Preferences;
import com.ebrg.secure9.activity.Accounts;
import com.ebrg.secure9.activity.ChooseKey;
import com.ebrg.secure9.activity.K9PreferenceActivity;
import com.ebrg.secure9.mail.security.Hash;
import com.ebrg.secure9.R;

public class EncryptionSettings extends K9PreferenceActivity 
{
	//Secure9
	private Account mAccount;
	static final String EXTRA_ACCOUNT = "account";
	public static int whichPref;
	private CheckBoxPreference mEncryptAll;
	private CheckBoxPreference mEncryptSubject;
	private CheckBoxPreference mDefaultToKey;
	private CheckBoxPreference mAes256;
	private ListPreference mAskForPin;
	private Object newPinPref;
	private String oldPinPref;


	public static void encryptionSettings(Context context, Account account)
	{
		Intent i = new Intent(context, EncryptionSettings.class);
		i.putExtra(EXTRA_ACCOUNT, account.getUuid());
		context.startActivity(i);
	}



	@Override
	public void onCreate(Bundle savedInstanceState)
	{
		super.onCreate(savedInstanceState);
		addPreferencesFromResource(R.xml.encryption_preferences);

		//Set up account
		String accountUuid = getIntent().getStringExtra(EXTRA_ACCOUNT);
		mAccount = Preferences.getPreferences(this).getAccount(accountUuid);

		mEncryptAll = (CheckBoxPreference)findPreference("encrypt_all"); 
		mEncryptAll.setChecked(mAccount.getEncryptAll()); 

		mAes256 = (CheckBoxPreference)findPreference("256_bit");
		mAes256.setChecked(mAccount.getAes256());

		mEncryptSubject = (CheckBoxPreference)findPreference("encrypt_subject");
		mEncryptSubject.setChecked(mAccount.getEncryptSubject());

		mDefaultToKey = (CheckBoxPreference)findPreference("use_key_by_default");
		mDefaultToKey.setChecked(mAccount.getUseKeyDefault());

		mAskForPin = (ListPreference)findPreference("ask_for_pin");
		mAskForPin.setValue(String.valueOf(mAccount.getAskForPin()));
		mAskForPin.setSummary(mAskForPin.getEntry());
		oldPinPref = mAskForPin.getValue();	
	
		if(!Hash.pinExists(EncryptionSettings.this, mAccount.getEmail()))
		{
			mAskForPin.setValueIndex(0);
			mAskForPin.setSummary("Never (No pin)");
		}

		//Confirm pin before allowing user to change sensitive settings (if pin exists)
		mAskForPin.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
			public boolean onPreferenceChange(Preference preference,Object newValue) 
			{
				oldPinPref = mAskForPin.getValue();	
				newPinPref = newValue;
				
				//Check for pin file
				boolean pinMatch = Hash.pinExists(EncryptionSettings.this,
						mAccount.getEmail());

				if(!newPinPref.equals(oldPinPref)){
					//If user is trying to change settings and has a pin, verify it.
					if(pinMatch)
						verifyPin();		
					else if(!pinMatch)
					{
						mAskForPin.setValueIndex(0);
						mAskForPin.setSummary("Never (No pin)");
						Toast.makeText(EncryptionSettings.this,"Account pin does not exist",Toast.LENGTH_SHORT).show();
					}
					//If no pin, make change.
					else
					{
						mAskForPin.setValue(newPinPref.toString());
						mAskForPin.setSummary(mAskForPin.getEntry());						
					}
				}
				else
					mAskForPin.setValue(oldPinPref);
				return pinMatch; 
			}


		});

		//New key action
		findPreference("setup_new_key").setOnPreferenceClickListener(
				new Preference.OnPreferenceClickListener()
				{
					public boolean onPreferenceClick(Preference preference)
					{
						onNewKey();
						return true;
					}
				});


		//Manage keys action
		findPreference("manage_keys").setOnPreferenceClickListener(
				new Preference.OnPreferenceClickListener()
				{
					public boolean onPreferenceClick(Preference preference)
					{
						onViewKeys();
						return true;
					}
				});


		//Manage PIN action
		findPreference("manage_pin").setOnPreferenceClickListener(
				new Preference.OnPreferenceClickListener()
				{
					public boolean onPreferenceClick(Preference preference)
					{
						onManagePin();
						return true;
					}
				});
	}

	public void onNewKey(){		
		EncryptionNewKey.actionNewKey(this,mAccount,"settings", "");
	}

	public void onManagePin(){		
		EncryptionPin.actionNewPin(this,mAccount);
	}

	private void onViewKeys()
	{

		Intent intent = new Intent(this, ChooseKey.class);
		intent.putExtra(ChooseKey.EXTRA_ACCOUNT, mAccount.getUuid());
		startActivityForResult(intent, 2);   

	}

	@Override
	public void onResume()
	{
		super.onResume();
	}


	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event)
	{

		if (keyCode == KeyEvent.KEYCODE_BACK)
		{
			saveSettings(keyCode,event);

			if (Secure9.manageBack())
			{
				Accounts.listAccounts(this);
				finish();
				return true;
			}
		}
		return super.onKeyDown(keyCode, event);
	}

	//Save settings when user hits the back button
	private void saveSettings(int keyCode, KeyEvent event)
	{   
		//Save settings
		mAccount.setUseKeyDefault(mDefaultToKey.isChecked());
		mAccount.setEncryptSubject(mEncryptSubject.isChecked());
		mAccount.setEncryptAll(mEncryptAll.isChecked());
		mAccount.setAskForPin(mAskForPin.getValue());
		mAccount.setAes256(mAes256.isChecked());
		mAccount.save(Preferences.getPreferences(this));	
	}

	private void verifyPin()
	{
		AlertDialog.Builder alert = new AlertDialog.Builder(this);
		alert.setTitle(R.string.verify_pin_dialog_title);
		alert.setMessage("PIN confirmation required to change this setting.");

		// Set an EditText view to get user input 
		final EditText input = new EditText(this);
		input.setInputType(InputType.TYPE_CLASS_PHONE);
		input.setTransformationMethod

		(android.text.method.PasswordTransformationMethod.getInstance());
		alert.setView(input);

		alert.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
			public void onClick(DialogInterface dialog, int whichButton) 
			{
			
				if(input.length() < 4)
				{
					// Wrong pin - reset to old pref
					mAskForPin.setValue(oldPinPref);
					mAccount.setAskForPin(oldPinPref.toString());
				    mAskForPin.setSummary(mAskForPin.getEntry());
					Toast.makeText(EncryptionSettings.this,R.string.pin_incorrect,Toast.LENGTH_LONG).show();
					return;
				}
				
				char[] pinInput = new char[input.getText().length()];
				for(int i = 0; i < input.getText().length(); i++)
					pinInput[i] = input.getText().charAt(i);
				
				FileInputStream fis;
				try 
				{
					fis = openFileInput((mAccount.getEmail().toLowerCase()) + EncryptionSettings.this.getString(R.string.legacy_pin_file_type));
					BufferedReader in = new BufferedReader(new InputStreamReader(fis));	
					char[] pinFromFile = in.readLine().toCharArray();
					
					boolean match = false;
					if(Arrays.equals(pinInput, pinFromFile))							
							match = true;
				
					if (match)
					{		
						//oldPinPref = mAskForPin.getValue();
						mAskForPin.setValue(newPinPref.toString());
						mAskForPin.setSummary(mAskForPin.getEntry());	
						oldPinPref = mAskForPin.getValue();
						Toast.makeText(EncryptionSettings.this,"Preference changed",Toast.LENGTH_SHORT).show();
						match = false; //reset pin verification
					}
				
					else
					{
						// Wrong pin - reset to old pref
						mAskForPin.setValue(oldPinPref);
						mAskForPin.setSummary(mAskForPin.getEntry());
						Toast.makeText(EncryptionSettings.this,R.string.pin_incorrect,Toast.LENGTH_LONG).show();
					}

					if(pinInput !=  null)
						Arrays.fill(pinInput, '0');
					if(pinFromFile !=  null)
						Arrays.fill(pinFromFile, '0');


				} 
				catch (FileNotFoundException e) 
				{
					//No .pin found, try .pin2
					try 
					{
						fis = openFileInput((mAccount.getEmail().toLowerCase()) + EncryptionSettings.this.getString(R.string.hashed_pin_file_type));
						BufferedReader in = new BufferedReader(new InputStreamReader(fis));	
						String pinFromFile = in.readLine();
						String storedRand = Hash.getRandom(pinFromFile, input.getText().length(), EncryptionSettings.this);
						String storedStatic = Hash.getStatic(pinFromFile, input.getText().length(), EncryptionSettings.this);

						String inputHash = Hash.verify(mAccount.getEmail(), 
								pinInput, storedRand, storedStatic);
			
			
						if (inputHash.equals(pinFromFile))
						{								
							mAskForPin.setValue(newPinPref.toString());
							mAskForPin.setSummary(mAskForPin.getEntry());
							oldPinPref = mAskForPin.getValue();
							Toast.makeText(EncryptionSettings.this,"Preference changed",Toast.LENGTH_SHORT).show();
						}

						else
						{
							// Wrong pin - reset to old pref
							mAskForPin.setValue(oldPinPref);
							mAccount.setAskForPin(oldPinPref.toString());
						    mAskForPin.setSummary(mAskForPin.getEntry());
							Toast.makeText(EncryptionSettings.this,R.string.pin_incorrect,Toast.LENGTH_LONG).show();
						}

						if(pinInput !=  null)
							Arrays.fill(pinInput, '0');

					} catch (FileNotFoundException e1) {
						Toast.makeText(EncryptionSettings.this,R.string.pin_not_found,Toast.LENGTH_LONG).show();

					} catch (IOException e1) {
						Toast.makeText(EncryptionSettings.this,R.string.error_key_io,Toast.LENGTH_LONG).show();
					}

				} catch (IOException e) {
					Toast.makeText(EncryptionSettings.this,"Error reading PIN file",Toast.LENGTH_LONG).show();
				}

			} 

		});

		alert.setNegativeButton(R.string.cancel_action, new DialogInterface.OnClickListener() 
		{
			public void onClick(DialogInterface dialog, int whichButton) 
			{
				// Canceled - reset to old pref
				mAskForPin.setValue(oldPinPref);
				mAskForPin.setSummary(mAskForPin.getEntry());
			}
		});

		alert.setIcon(R.drawable.pin);
		alert.show();
	}
}

